package net.esj.basic.core.engine.schedule;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledFuture;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.util.Assert;

public class ScheduleFactory  implements InitializingBean, DisposableBean {
	
	private static final Logger logger = Logger.getLogger(ScheduleFactory.class);

	private Map<String, ScheduledFuture> scheduledFutures = new HashMap<String, ScheduledFuture>();
	
	private TaskScheduler taskScheduler; 
	
	private Executor executor; 

	public static final String THREAD_NAME_PERFIX = "net.melon.core.scheduler-";
	
	@Override
	public void afterPropertiesSet() throws Exception {
		((ThreadPoolTaskScheduler)this.taskScheduler).setThreadNamePrefix(THREAD_NAME_PERFIX);
	}

	@Override
	public void destroy() throws Exception {
		for (ScheduledFuture<?> future : this.scheduledFutures.values()) {
			future.cancel(true);
		}
	}

	public void setTaskScheduler(TaskScheduler taskScheduler) {
		Assert.notNull(taskScheduler, "TaskScheduler must not be null");
		this.taskScheduler = taskScheduler;
	}
	
	public void setExecutor(Executor executor) {
		Assert.notNull(executor, "executor must not be null");
		this.executor = executor;
	}

	public ScheduledFuture schedule(Scheduler scheduler) {
		ScheduledFuture sf  = null;
		switch(scheduler.resolveScheduleType()){
		case Scheduler.SCHEDULE_TYPE_CRON:
			sf = taskScheduler.schedule(scheduler, new CronTrigger(scheduler.getCronAttribute()));
			scheduledFutures.put(scheduler.getKey(), sf);
			return sf;
		case Scheduler.SCHEDULE_TYPE_FIXED_DELAY:
			sf = taskScheduler.scheduleWithFixedDelay(scheduler, scheduler.getFixedDelayAttribute());
			scheduledFutures.put(scheduler.getKey(), sf);
			return sf;
		case Scheduler.SCHEDULE_TYPE_FIXED_RATE:
			sf = taskScheduler.scheduleAtFixedRate(scheduler, scheduler.getFixedRateAttribute());
			scheduledFutures.put(scheduler.getKey(), sf);
			return sf;
		case Scheduler.SCHEDULE_TYPE_TRIGGER:
			sf = taskScheduler.schedule(scheduler, scheduler.getTrigger());
			scheduledFutures.put(scheduler.getKey(), sf);
			return sf;
		default :
			return sf;
		}
	}

	/**
	 * 取消某个任务
	 * @param key
	 * @return
	 */
	public boolean cancel(String key){
		ScheduledFuture sf =scheduledFutures.get(key);
		if(sf!=null){
			logger.debug("Schedule:["+key+"] has been canceled");
			return sf.cancel(true);
		}
		return false;
	}
}
